﻿#include "FITKAbaqusAdaptorInertia.h"
#include "InpKeyLineSpliter.h"
#include "FITKAbaqusINPReader.h"
#include "FITKAbaqusINPWriter.h"
#include "FITKAbaqusGetInterfaceTool.h"
#include "FITK_Component/FITKAbaqusData/FITKDataCase.h"
#include "FITK_Interface/FITKInterfaceModel/FITKModelSet.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKAbstractLoadBC.h"
#include "FITK_Interface/FITKInterfaceModel/FITKAbstractModel.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInertiaPointMassInertia.h"
#include "FITK_Component/FITKAbaqusData/FITKAbaqusPart.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAssembly.h"
#include "FITK_Interface/FITKInterfaceModel/FITKCoordinateSystem.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaTransform.h"
#include <QTextStream>
#include <QList>
#include <QDebug>

//set集合每行不得超过16个，INP准则
#define SETCOUNT 16

namespace IO
{

    QString FITKAbaqusAdaptorInertia::getAdaptorClass()
    {
        return "FITKAbaqusAdaptorInertia";
    }

    bool FITKAbaqusAdaptorInertia::adaptR()
    {
        if (!_reader)return false;
        //回退一行 处理关键字信息
        _reader->backLine();
        QString line = _reader->readLine();
        //关键字处理
        InpKeyLineSpliter s(line, _reader);
        QString sH = s.getHeader().toLower();
        bool readOK = false;
        if (sH == "mass")
            readOK = this->readPointMassa();
        else if (sH == "rotary inertia")
            readOK = this->readRotaryInertia();
        return readOK;
    }

    bool FITKAbaqusAdaptorInertia::adaptW()
    {
        Interface::FITKAbaAbstractInertia* inertia = dynamic_cast<Interface::FITKAbaAbstractInertia*>(_dataObj);
        if (!inertia || !_writer)return false;
        bool ok = false;
        Interface::FITKAbaAbstractInertia::FITKAbaInertiaType type = inertia->getInertiaType();
        if (type == Interface::FITKAbaAbstractInertia::FITKAbaInertiaType::PointMassInertia)
            ok = this->writePointMassInertia();
        else if (type == Interface::FITKAbaAbstractInertia::FITKAbaInertiaType::NonstructuralMass)
            ok = this->writeNonstructuralMass();
        else if (type == Interface::FITKAbaAbstractInertia::FITKAbaInertiaType::HeatCapacitance)
            ok = this->writeHeatCapacitance();
        return ok;
    }

    void FITKAbaqusAdaptorInertia::setWriteElementId(int *writeElementId)
    {
        _writeElementId = writeElementId;
    }

    void FITKAbaqusAdaptorInertia::setPartData(AbaqusData::FITKAbaqusPart* partData)
    {
        _partData = partData;
    }

    void FITKAbaqusAdaptorInertia::setAssemblyData(Interface::FITKAbaAssembly* assemblyData)
    {
        _assemblyData = assemblyData;
    }

    bool FITKAbaqusAdaptorInertia::readPointMassa()
    {
        Interface::FITKAbaInertiaPointMassInertia* pointMassInertia = dynamic_cast<Interface::FITKAbaInertiaPointMassInertia*>(_dataObj);
        if (!pointMassInertia || !_reader)return false;
        //回退一行 处理关键字信息
        _reader->backLine();
        QString line = _reader->readLine();
        //关键字处理
        InpKeyLineSpliter s(line, _reader);
        QString sH = s.getHeader().toLower();
        //获取名称并设置
        QString name = s["elset"];
        pointMassInertia->setDataObjectName(name);
        //获取类型 - 各向异性
        if (s["type"].trimmed().toUpper() == "ANISOTROPIC")
            pointMassInertia->setMassType(Interface::FITKAbaInertiaPointMassInertia::MassType::Anisotropic);
        bool ok = false;
        if (s.hasKey("alpha"))
        {
            double alpha = s["alpha"].toDouble(&ok);
            if (!ok)return false;
            pointMassInertia->setAlpha(alpha);
        }
        if (s.hasKey("composite"))
        {
            double composite = s["composite"].toDouble(&ok);
            if (!ok)return false;
            pointMassInertia->setComposite(composite);
        }
        //局部坐标系
        if (s.hasKey("orientation"))
        {
            int csysId = -1;
            if (!this->getCsysIdByName(QString("Ori_%1").arg(s["orientation"]), csysId))return false;
            pointMassInertia->setCsysId(csysId);
        }

        //读取数据
        line = _reader->readLine();
        if (line.startsWith("*"))return false;
        QStringList str = line.split(',');
        //获取各向同性的质量值
        if (pointMassInertia->getMassType() == 
            Interface::FITKAbaInertiaPointMassInertia::MassType::Isotropic)
        {
            if (str.isEmpty())return false;
            double value = str.at(0).trimmed().toDouble(&ok);
            if (!ok)return false;
            pointMassInertia->setIsoTropicMass(value);
        }
        //获取各向异性的质量值
        else if (pointMassInertia->getMassType() == 
            Interface::FITKAbaInertiaPointMassInertia::MassType::Anisotropic)
        {
            if (str.size() < 3)return false;
            double m11 = str.at(0).trimmed().toDouble(&ok);
            if (!ok)return false;
            double m22 = str.at(1).trimmed().toDouble(&ok);
            if (!ok)return false;
            double m33 = str.at(2).trimmed().toDouble(&ok);
            if (!ok)return false;
            pointMassInertia->setM11(m11);
            pointMassInertia->setM22(m22);
            pointMassInertia->setM33(m33);
        }
        return true;
    }

    bool FITKAbaqusAdaptorInertia::readRotaryInertia()
    {
        Interface::FITKAbaInertiaPointMassInertia* pointMassInertia = dynamic_cast<Interface::FITKAbaInertiaPointMassInertia*>(_dataObj);
        if (!pointMassInertia || !_reader)return false;
        //回退一行 处理关键字信息
        _reader->backLine();
        QString line = _reader->readLine();
        //关键字处理
        InpKeyLineSpliter s(line, _reader);
        QString sH = s.getHeader().toLower();
        //获取名称并设置
        QString name = s["elset"];
        pointMassInertia->setDataObjectName(name);
        bool ok = false;
        if (s.hasKey("alpha"))
        {
            double alpha = s["alpha"].toDouble(&ok);
            if (!ok)return false;
            pointMassInertia->setAlpha(alpha);
        }
        if (s.hasKey("composite"))
        {
            double composite = s["composite"].toDouble(&ok);
            if (!ok)return false;
            pointMassInertia->setComposite(composite);
        }
        //局部坐标系
        if (s.hasKey("orientation"))
        {
            int csysId = -1;
            if (!this->getCsysIdByName(QString("Ori_%1").arg(s["orientation"]), csysId))return false;
            pointMassInertia->setCsysId(csysId);
        }

        //读取数据
        line = _reader->readLine();
        if (line.startsWith("*"))return false;
        QStringList str = line.split(',');
        //获取转动惯量数值
        QList<double> valueList;
        for (QString v : str)
        {
            double value = v.toDouble(&ok);
            if (!ok)return false;
            valueList.append(value);
            if (valueList.size() == 6)break;
        }
        if (valueList.isEmpty())return false;
        //设置数据I11
        pointMassInertia->setI11(valueList.at(0));
        if (valueList.size() > 3)
            pointMassInertia->setSpecifyOffDiagnalTerms(true);
        //设置数据I22
        if (valueList.size() > 1)
            pointMassInertia->setI22(valueList.at(1));
        //设置数据I33
        if (valueList.size() > 2)
            pointMassInertia->setI33(valueList.at(2));
        //设置数据I12
        if (valueList.size() > 3)
            pointMassInertia->setI12(valueList.at(3));
        //设置数据I13
        if (valueList.size() > 4)
            pointMassInertia->setI13(valueList.at(4));
        //设置数据I23
        if (valueList.size() > 5)
            pointMassInertia->setI23(valueList.at(5));
        return true;
    }

    bool FITKAbaqusAdaptorInertia::getCsysIdByName(QString orientationName, int &csysId)
    {
        if (_partData)
        {
            //获取局部坐标系管理器
            auto transformManager = _partData->getCoordinateSystemManager();
            auto transformData = transformManager->getDataByName(orientationName);
            if (!transformData)return false;
            csysId = transformData->getDataObjectID();
            return true;
        }
        else if (_assemblyData)
        {
            //获取局部坐标系管理器
            auto transformManager = _assemblyData->getTransformManager();
            auto transformData = transformManager->getDataByName(orientationName);
            if (!transformData)return false;
            csysId = transformData->getDataObjectID();
            return true;
        }
        return false;
    }

    bool FITKAbaqusAdaptorInertia::writeElement(QString type)
    {
        Interface::FITKAbaAbstractInertia* inertia = dynamic_cast<Interface::FITKAbaAbstractInertia*>(_dataObj);
        if (!inertia || !_writer || !_writeElementId)return false;
        QTextStream* stream = _writer->getStream();
        //获取集合
        Interface::FITKModelSet* set = dynamic_cast<Interface::FITKModelSet*>(inertia->getComponentObj());
        if (!set)return false;
        //获取模型Id
        int modelId = inertia->getModelID();
        //获取集合名称
        QString name = QString("%1_%2_").arg(set->getDataObjectName()).arg(inertia->getDataObjectName());
        name = name.contains(' ')? QString("\"%1\"").arg(name) : name;
        QString lineOne = QString("*Element, type=%1, elset=%2").arg(type).arg(name);
        *stream << lineOne << endl;
        //写出编号
        if (set->isCombination())
        {
            int count = set->getDataCount();
            for (int i = 0; i < count; ++i)
            {
                Interface::FITKModelSet* childSet = set->getDataByIndex(i);
                if (!this->writeElementID(childSet, modelId))return false;
            }
        }
        else
            if (!this->writeElementID(set, modelId))return false;
        return true;
    }

    bool FITKAbaqusAdaptorInertia::writeElementID(Interface::FITKModelSet* set, int modelId)
    {
        if (!set)return false;
        QTextStream* stream = _writer->getStream();
        //获取成员编号
        QList<int> mList = set->getAbsoluteMember();
        //获取模型名称
        QString modelName{};
        if (set->getAbstractModel() != nullptr && set->getAbstractModel()->getAbsModelType() == Interface::FITKModelEnum::AbsModelType::AssInstance)
        {
            auto childModel = set->getAbstractModel();
            if (!childModel)return false;
            modelName = childModel->getDataObjectName();
            modelName = modelName.contains(' ') ? QString("\"%1\"").arg(modelName) : modelName;
        }

        //写出成员编号
        for (int id : mList)
        {
            ++(*_writeElementId);
            if (modelName.isEmpty())
                *stream << QString("%1, %2").arg((*_writeElementId)).arg(id) << endl;
            else
                *stream << QString("%1, %2.%3").arg((*_writeElementId)).arg(modelName).arg(id) << endl;
        }
        return true;
    }

    bool FITKAbaqusAdaptorInertia::writePointMassInertia()
    {
        Interface::FITKAbaInertiaPointMassInertia* pointMassInertia = dynamic_cast<Interface::FITKAbaInertiaPointMassInertia*>(_dataObj);
        if (!pointMassInertia || !_writer)return false;
        //判断是否写出质量点或转动惯量
        bool isWritePointMass = false, isWriteRotaryInertia = false;
        //质量点
        if (pointMassInertia->getMassType() == 
            Interface::FITKAbaInertiaPointMassInertia::MassType::Isotropic)
        {
            if (fabs(pointMassInertia->getIsoTropicMass()) > 1e-16)
                isWritePointMass = true;
        }
        else if (pointMassInertia->getMassType() == 
            Interface::FITKAbaInertiaPointMassInertia::MassType::Anisotropic)
        {
            if (fabs(pointMassInertia->getM11()) > 1e-16 || fabs(pointMassInertia->getM22()) > 1e-16 || fabs(pointMassInertia->getM33()) > 1e-16)
                isWritePointMass = true;
        }
        //转动惯量
        if (fabs(pointMassInertia->getI11()) > 1e-16 || fabs(pointMassInertia->getI22()) > 1e-16 || fabs(pointMassInertia->getI33()) > 1e-16)
            isWriteRotaryInertia = true;
        if (!isWriteRotaryInertia && pointMassInertia->getSpecifyOffDiagnalTerms())
        {
            if (fabs(pointMassInertia->getI12()) > 1e-16 || fabs(pointMassInertia->getI13()) > 1e-16 || fabs(pointMassInertia->getI23()) > 1e-16)
                isWriteRotaryInertia = true;
        }
        //写出数据
        if (isWritePointMass)
            if (!this->writePointMass())return false;
        if (isWriteRotaryInertia)
            if (!this->writeRotaryInertia())return false;
        return true;
    }

    bool FITKAbaqusAdaptorInertia::writePointMass()
    {
        Interface::FITKAbaInertiaPointMassInertia* pointMassInertia = dynamic_cast<Interface::FITKAbaInertiaPointMassInertia*>(_dataObj);
        if (!pointMassInertia || !_writer)return false;
        if (!this->writeElement("MASS"))return false;
        QTextStream* stream = _writer->getStream();
        //获取集合名称
        auto set = pointMassInertia->getComponentObj();
        if (!set)return false;
        QString name = QString("%1_%2_").arg(set->getDataObjectName()).arg(pointMassInertia->getDataObjectName());
        name = name.contains(' ') ? QString("\"%1\"").arg(name) : name;
        QString lineOne = QString("*Mass, elset=%1").arg(name);
        //局部坐标系
        QString orientationName = this->getCsysNameById(pointMassInertia->getCsysId());
        orientationName = orientationName.contains(' ') ? QString("\"%1\"").arg(orientationName) : orientationName;
        if (!orientationName.isEmpty())
            lineOne += QString(", orientation=%1").arg(orientationName);
        //alpha
        double alpha = pointMassInertia->getAlpha();
        if (fabs(alpha) > 1e-16)
            lineOne += QString(", alpha=%1").arg(_writer->double2String(alpha, 9, 0));
        //复合
        double composite = pointMassInertia->getComposite();
        if (fabs(composite) > 1e-16)
            lineOne += QString(", composite=%1").arg(_writer->double2String(composite, 9, 0));
        //局部坐标系
        //写出Mass
        *stream << lineOne << endl;
        //质量类型
        if (pointMassInertia->getMassType() == 
            Interface::FITKAbaInertiaPointMassInertia::MassType::Isotropic)
            *stream << QString("%1,").arg(_writer->double2String(pointMassInertia->getIsoTropicMass(), 9, 0)) << endl;
        else if (pointMassInertia->getMassType() == 
            Interface::FITKAbaInertiaPointMassInertia::MassType::Anisotropic)
            *stream << QString("%1, %2, %3").arg(_writer->double2String(pointMassInertia->getM11(), 9, 0)).arg(_writer->double2String(pointMassInertia->getM22(), 9, 0)).arg(_writer->double2String(pointMassInertia->getM33(), 9, 0)) << endl;
        return true;
    }

    bool FITKAbaqusAdaptorInertia::writeRotaryInertia()
    {
        Interface::FITKAbaInertiaPointMassInertia* pointMassInertia = dynamic_cast<Interface::FITKAbaInertiaPointMassInertia*>(_dataObj);
        if (!pointMassInertia || !_writer)return false;
        if (!this->writeElement("ROTARYI"))return false;
        QTextStream* stream = _writer->getStream();
        //获取集合名称
        auto set = pointMassInertia->getComponentObj();
        if (!set)return false;
        QString name = QString("%1_%2_").arg(set->getDataObjectName()).arg(pointMassInertia->getDataObjectName());
        QString lineOne = QString("*Rotary Inertia, elset=%1").arg(name);
        //局部坐标系
        QString orientationName = this->getCsysNameById(pointMassInertia->getCsysId());
        orientationName = orientationName.contains(' ') ? QString("\"%1\"").arg(orientationName) : orientationName;
        if (!orientationName.isEmpty())
            lineOne += QString(", orientation=%1").arg(orientationName);
        //alpha
        double alpha = pointMassInertia->getAlpha();
        if (fabs(alpha) > 1e-16)
            lineOne += QString(", alpha=%1").arg(_writer->double2String(alpha, 9, 0));
        //复合
        double composite = pointMassInertia->getComposite();
        if (fabs(composite) > 1e-16)
            lineOne += QString(", composite=%1").arg(_writer->double2String(composite, 9, 0));
        //局部坐标系
        //写出Rotary Inertia
        *stream << lineOne << endl;
        //写出数据
        lineOne = QString("%1, %2, %3").arg(_writer->double2String(pointMassInertia->getI11(), 9, 0)).arg(_writer->double2String(pointMassInertia->getI22(), 9, 0)).arg(_writer->double2String(pointMassInertia->getI33(), 9, 0));
        if (pointMassInertia->getSpecifyOffDiagnalTerms())
            lineOne += QString(", %4, %5, %6").arg(_writer->double2String(pointMassInertia->getI12(), 9, 0)).arg(_writer->double2String(pointMassInertia->getI13(), 9, 0)).arg(_writer->double2String(pointMassInertia->getI23(), 9, 0));
        *stream << lineOne << endl;
        return true;
    }

    bool FITKAbaqusAdaptorInertia::writeNonstructuralMass()
    {
        return false;
    }

    bool FITKAbaqusAdaptorInertia::writeHeatCapacitance()
    {
        return false;
    }

    QString FITKAbaqusAdaptorInertia::getCsysNameById(int csysId)
    {
        QString name;
        if (_partData)
        {
            //获取局部坐标系管理器
            auto transformManager = _partData->getCoordinateSystemManager();
            auto transformData = transformManager->getDataByID(csysId);
            if (!transformData)return name;
            return transformData->getDataObjectName();
        }
        else if (_assemblyData)
        {
            //获取局部坐标系管理器
            auto transformManager = _assemblyData->getTransformManager();
            auto transformData = transformManager->getDataByID(csysId);
            if (!transformData)return name;
            return transformData->getDataObjectName();
        }
        return name;
    }
}
